import os
import sys

import requests
import re
from tqdm import tqdm
import pandas as pd
from tabulate import tabulate

current_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(current_dir, "."))
sys.path.append(os.path.join(current_dir, "../"))
sys.path.append(os.path.join(current_dir, "../.."))


def param_type(source_type: str):
    """
    将文档中的数据类型转换成python数据类型
    :param source_type:
    :return:
    """
    if source_type == "String":
        return "str"
    elif source_type == "Integer":
        return "int"
    elif source_type == "Float":
        return "float"
    else:
        return "str"


def indent(source: str, count: int):
    """
    代码缩进
    :param source:
    :param count:
    :return:
    """
    return "\n".join([(" " * count) + row for row in source.split("\n")])


def columns_dict(return_list: list):
    """
    生成列类型词典
    :param return_list:
    :return:
    """
    col_str = "column_type_dict = {" + (
        ", ".join(["'" + p['参数名'] + "': '" + param_type(p['类型']) + "'" for p in return_list if
                   '参数名' in p and '类型' in p])) + "}"
    return col_str


def columns_name_dict(return_list: list):
    """
    生成列中英文名称词典
    :param return_list:
    :return:
    """
    col_str = "column_name_dict = {" + (
        ", ".join(["'" + p['参数名'] + "': '" + p['说明'] + "'" for p in return_list if
                   '参数名' in p and '类型' in p])) + "}"
    return col_str


def convert_params(params_list: list):
    """
    生成参数
    :param params_list:
    :return:
    """
    return ", ".join([p['名称'] + ": " + param_type(p['类型']) + " = None" for p in params_list]+["**kwargs"])


def all_api(api_dict_list):
    """
    生成all_api 方法,方便接口查询
    :param api_dict_list:
    :return:
    """
    return """
def all_api(keyword:str = None):
    all_api_list={api_dict_list}
    df=pd.DataFrame(all_api_list)
    if keyword is None:
        return df
    else:
        return df[(df['method'].str.contains(keyword))|(df['description'].str.contains(keyword))]        
    """.format(**locals())


def template(module: str, method: str, description: str, params: str, param_doc: str, return_doc: str, doc_url: str,
             column_dict: str, column_name_dict: str):
    """
    生成对应的接口函数
    :param module:
    :param method:
    :param description:
    :param params:
    :param param_doc:
    :param return_doc:
    :param doc_url:
    :param column_dict:
    :param column_name_dict:
    :return:
    """
    dict_value = "{}"
    return """
def {method}({params})->Query:
    \"\"\"
    {description}
    {doc_url}
    <参数>
{param_doc}
    <返回结果>
{return_doc}
    \"\"\"
    params = locals().copy()
    real_params = {dict_value}
    {column_dict}
    {column_name_dict}
    for k, v in params.items():
        if v is not None and k != 'kwargs':
            real_params[k] = v
    for k,v in kwargs.items():
        if v is not None:
            real_params[k] = v
    return Query(module="{module}", method="{method}", params=real_params,return_column_type_dict=column_type_dict,return_column_name_dict=column_name_dict)    
    """.format(**locals())


def generate_api():
    resp = requests.get(
        "https://udata.hs.net/udata/business/v1/web_services/operator/library/get_library_detail?libraryId=1")
    doc_ids = re.findall("\"document_id\":(\d+)", resp.text)
    codes = []
    methods = []
    api_dict_list = []
    for doc_id in tqdm(doc_ids):
        resp_doc = requests.get(
            "https://udata.hs.net/udata/business/v1/web_services/operator/get_document?documentId=" + doc_id)
        doc_url = "https://udata.hs.net/datas/" + doc_id + "/"
        description = resp_doc.json()['data']['description']
        html = resp_doc.json()['data']['content']
        dfs = pd.read_html(html)
        params_doc = tabulate(dfs[1].fillna("").to_dict('records'), headers="keys", tablefmt='simple')
        return_doc = tabulate(dfs[2].fillna("").to_dict('records'), headers="keys", tablefmt='simple')
        params_list = dfs[1].to_dict("records")
        return_list = dfs[2].to_dict("records")
        params = convert_params(params_list)
        column_dict = columns_dict(return_list)
        name_dict = columns_name_dict(return_list)
        parts = dfs[0]['url'].iloc[0].split("/")
        module = parts[-2]
        method = parts[-1]
        codes.append(
            template(module, method, description, params, indent(params_doc, 4), indent(return_doc, 4), doc_url,
                     column_dict, name_dict))
        methods.append(method)
        api_dict_list.append({"module": module, "method": method, "description": description,
                              'url': doc_url})
    with open("./api.py", 'w', encoding='utf-8') as f:
        f.write("from hysdata.models import Query\nimport pandas as pd\n")
        f.write("\n\n".join(codes))
        f.write("\n\n" + all_api(api_dict_list))
        f.write("\n\n__all__ = ['" + "', '".join(methods) + "']\n")


if __name__ == "__main__":
    generate_api()
